package glossos.parsing.fsm;

import glossos.parsing.CharMatcher;
import glossos.parsing.Parser;
import static glossos.parsing.CharMatcher.JAVA_LETTER_OR_DIGIT;
import static glossos.parsing.CharMatcher.JAVA_WHITESPACE;
import glossos.parsing.WordBuffer;
import glossos.parsing.action.*;

import java.io.Reader;

/**
 * A static factory for {@link Parser}s.
 * @author Otavio Macedo
 *
 */
public class Parsers {
	private static final CharMatcher SENTENCE_DELIMITER = CharMatcher.anyOf(",.;?!:");
	private static final CharMatcher DASH = CharMatcher.is('-');

	public static Parser newSentenceParser(Reader reader, WordBuffer buffer){
		Action appendAction = new AppendAction(buffer);
		Action appendCandidateAction = new AppendCandidateAction(buffer);
		Action endSentenceAction = new EndSentenceAction(buffer);
		Action lookaheadAction = new LookaheadAction(buffer);
		Action finishAction = new FinishAction(buffer);
        Action nullAction = new NullAction();
		
		State alphanumReceived = new State("received letter or digit");
		State whitespaceReceived = new State("recieved whitespace");
		State delimiterReceived = new State("received delimiter");
		State firstDashReceived = new State("received dash");
		State secondDashReceived = new State("received second dash");

        alphanumReceived
			.addTransition(new Transition(JAVA_LETTER_OR_DIGIT, appendAction, alphanumReceived))
			.addTransition(new Transition(JAVA_WHITESPACE, nullAction, whitespaceReceived))
			.addTransition(new Transition(SENTENCE_DELIMITER, endSentenceAction, delimiterReceived))
			.addTransition(new Transition(DASH, appendCandidateAction, firstDashReceived));
		
		whitespaceReceived
			.addTransition(new Transition(JAVA_LETTER_OR_DIGIT, lookaheadAction, alphanumReceived))
			.addTransition(new Transition(JAVA_WHITESPACE, nullAction, whitespaceReceived))
			.addTransition(new Transition(SENTENCE_DELIMITER, endSentenceAction, delimiterReceived))
			.addTransition(new Transition(DASH, appendCandidateAction, firstDashReceived));
		
		delimiterReceived
			.addTransition(new Transition(JAVA_LETTER_OR_DIGIT, appendAction, alphanumReceived))
			.addTransition(new Transition(JAVA_WHITESPACE, nullAction, whitespaceReceived))
			.addTransition(new Transition(SENTENCE_DELIMITER, nullAction, delimiterReceived))
			.addTransition(new Transition(DASH, nullAction, delimiterReceived));

		firstDashReceived
			.addTransition(new Transition(DASH, endSentenceAction, secondDashReceived))
			.addTransition(new Transition(JAVA_LETTER_OR_DIGIT, appendAction, alphanumReceived))
			.addTransition(new Transition(JAVA_WHITESPACE, nullAction, whitespaceReceived))
			.addTransition(new Transition(SENTENCE_DELIMITER, endSentenceAction, secondDashReceived));

		secondDashReceived
			.addTransition(new Transition(JAVA_LETTER_OR_DIGIT, lookaheadAction, alphanumReceived))
			.addTransition(new Transition(JAVA_WHITESPACE, nullAction, whitespaceReceived))
			.addTransition(new Transition(SENTENCE_DELIMITER, nullAction, secondDashReceived))	
			.addTransition(new Transition(DASH, endSentenceAction, secondDashReceived));
		
        return new FiniteStateMachine(reader, alphanumReceived, finishAction);
	}
}
